using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using VisualizationPackage.FileLoader;
using VisualizationPackage.Contours;
using VisualizationPackage;
using VisualizationPackage.Simple_Coloring;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using GraphicsAPIs;
using VisualizationPackage.VectorField;
using VisualizationPackage.IsoSurfaces;
using System.Collections.ObjectModel;
namespace VisualUI
{
    public partial class frmMain : DrawingBox
    {
        Visualization.Mesh dtFile = null;
        int colorsCount = 10;
        ColorMap map = new ColorMap();
        frmVariables vars = new frmVariables();
        frmVectorField varsVector = new frmVectorField();
        bool _useExistingColorMap = false;
        ColorMap mapTemp = new ColorMap();

        List<Polygon> plFloodedContour1,
            plFloodedContour2,
            plIsoSurface,
            plStreamRibon,
            plSurfaceColor;
        List<VisualizationPackage.FileLoader.Line> lnMesh,
            lnEdgeColor,
            lnLineContour,
            lnStreamLine;

        public frmMain()
        {
            InitializeComponent();
            //InitializeDevice();
            //InitializeCam();
            //device.DeviceReset += new EventHandler(device_DeviceReset);
            
            Polygon p = new Polygon();
            p.Vertics.Add(new Vertex());
            p.Vertics[0][Constants.X_Coord] = 2;
            p.Vertics[0][Constants.Y_Coord] = 0;
            p.Vertics[0][Constants.Z_Coord] = 0;
            //MessageBox.Show(p.Vertics[0].CompareTo(p.Vertics[0]).ToString());
            p.Vertics.Add(new Vertex());
            p.Vertics[1][Constants.X_Coord] = -2;
            p.Vertics[1][Constants.Y_Coord] = 2;
            p.Vertics[1][Constants.Z_Coord] = 2;

            Vertex V1 = p.Vertics[0];
            Vertex other = p.Vertics[1];
            Vector3 v1 = new Vector3((float)V1[Constants.X_Coord], (float)V1[Constants.Y_Coord], (float)V1[Constants.Z_Coord]);
            Vector3 v2 = new Vector3((float)other[Constants.X_Coord], (float)other[Constants.Y_Coord], (float)other[Constants.Z_Coord]);

            Vector3 v = Vector3.Cross(v1, v2);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlgOpen = new OpenFileDialog();
            DialogResult dlgRes = dlgOpen.ShowDialog();
            if (dlgRes == DialogResult.OK)
            {
                dtFile = Loader.LoadFile(dlgOpen.FileName);
                foreach (string var in dtFile.VarToIndex.Keys)
                    GlobalVariables.Data[(int)dtFile.VarToIndex[var]] = var.ToUpper();
                // Ref : 1
                // GlobalVariables.Data[GlobalVariables.Data.Count] = "R";

                ResetAll();
                DrawMesh();
                meshToolStripMenuItem.Checked = true;
                Invalidate();
            }
        }

        private void ResetAll()
        {
            DisableAllLine();
            DisableAllSurface();
            
            lnEdgeColor = null;
            lnMesh = null;
            lnStreamLine = null;
            lnLineContour = null;

            plFloodedContour1 = null;
            plFloodedContour2 = null;
            plIsoSurface = null;
            plStreamRibon = null;
            plSurfaceColor = null;
            
            RefreshLines();
            RefreshPolygons();
        }

        private void DrawMesh()
        {
            map.Map.Clear();
            map[0] = Color.LightBlue;

            SimpleColoring clr = new SimpleColoring(map, Constants.X_Coord);
            lnMesh = new List<VisualizationPackage.FileLoader.Line>(clr.EdgeColoring(dtFile.Zones.Top()));
            RefreshLines();
            Invalidate();
        }

        private bool BuildColorMap(string Distribution)
        {
            if (Distribution == null || Distribution == "")
                return false;
            if (_useExistingColorMap)
            {
                map = mapTemp;
                return true;
            }
            double min = double.MaxValue, max = double.MinValue;
            foreach (Visualization.Vertex v in dtFile.Zones.Top().Vertices)
            {
                Vertex vNew = new Vertex(v);
                if (min > vNew[Distribution])
                    min = vNew[Distribution];
                if (max < vNew[Distribution])
                    max = vNew[Distribution];
            }
            //map[min] = Color.FromArgb(0, 6, 255);
            //map[10.9672] = Color.FromArgb(0, 75, 255);
            //map[18.1939] = Color.FromArgb(0, 218, 255);
            //map[21.8072] = Color.FromArgb(0, 255, 147);
            //map[25.4205] = Color.FromArgb(6, 255, 0);
            //map[29.0338] = Color.FromArgb(143, 255, 0);
            //map[32.6471] = Color.FromArgb(255, 244, 0);
            //map[36.2603] = Color.FromArgb(255, 75, 0);
            //map[39.8738] = Color.FromArgb(255, 6, 0);
            //map[max+5] = Color.FromArgb(255, 6, 0);
            //return true;
            map = ColorMap.Generate(min, max, colorsCount);
            double step = (max - min) / colorsCount;
            map[max + step] = Color.FromArgb(255, 0, 0);
            return true;
            map[min] = Color.FromArgb(0, 0, 255);
            map[min += step] = Color.FromArgb(0, 127, 255);
            map[min += step] = Color.FromArgb(0, 255, 255);
            map[min += step] = Color.FromArgb(0, 255, 127);
            map[min += step] = Color.FromArgb(0, 255, 0);
            map[min += step] = Color.FromArgb(127, 255, 0);
            map[min += step] = Color.FromArgb(255, 255, 0);
            map[min += step] = Color.FromArgb(255, 127, 0);
            map[min += step] = Color.FromArgb(255, 0, 0);
            map[min += step] = Color.FromArgb(255, 0, 0);
            return true;
        }

        private void DisableAllSurface()
        {
            floodedContoursToolStripMenuItem.Checked = false;
            floodedContoursMethod1ToolStripMenuItem.Checked = false;
            surfaceColoringToolStripMenuItem.Checked = false;
            isoSurfaceToolStripMenuItem.Checked = false;
        }
        private void DisableAllLine()
        {
            lineContoursToolStripMenuItem.Checked = false;
            streamLinesToolStripMenuItem.Checked = false;
            edgeColoringToolStripMenuItem.Checked = false;
        }
        
        #region Polygon Fillers
        private void surfaceColoringToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (surfaceColoringToolStripMenuItem.Checked)
            {
                plSurfaceColor = null;
                //if (Polygons != null)
                //    Polygons.Clear();
            }
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                SimpleColoring clr = new SimpleColoring(map, ChooseVariable(false));
                plSurfaceColor = new List<Polygon>(clr.SurfaceColoring(dtFile.Zones.Top()));
                
                //DisableAllSurface();
            }
            RefreshPolygons();
            Invalidate();
            surfaceColoringToolStripMenuItem.Checked = !surfaceColoringToolStripMenuItem.Checked;
        }
        private void floodedContoursToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (floodedContoursToolStripMenuItem.Checked)
            {
                //if (Polygons != null)
                //    Polygons.Clear();
                plFloodedContour2 = null;
            }
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                Contour cont = new Contour(GlobalVariables.Get(ChooseVariable(false)), map);
                plFloodedContour2 = new List<Polygon>(cont.FloodedContour(dtFile.Zones.Top()));
                
                //SetPolygons(polys);
                //DisableAllSurface();
            }
            RefreshPolygons();
            Invalidate();
            floodedContoursToolStripMenuItem.Checked = !floodedContoursToolStripMenuItem.Checked;
        }
        private void isoSurfaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (isoSurfaceToolStripMenuItem.Checked)
            {
                plIsoSurface = null;
                //if (Polygons != null)
                //    Polygons.Clear();
            }
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                MarchingCubes march = new MarchingCubes(map, GlobalVariables.Get(ChooseVariable(false)));
                plIsoSurface = new List<Polygon>(march.IsoSurfaces(dtFile.Zones.Top()));
                
                //SetPolygons(new List<Polygon>(polygons));

                //DisableAllSurface();
            }
            RefreshPolygons();
            Invalidate();
            isoSurfaceToolStripMenuItem.Checked = !isoSurfaceToolStripMenuItem.Checked;
        }
        private void floodedContoursMethod1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (floodedContoursMethod1ToolStripMenuItem.Checked)
            {
                plFloodedContour1 = null;
                //if (Polygons != null)
                //    Polygons.Clear();
            }
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                Contour cont = new Contour(GlobalVariables.Get(ChooseVariable(false)), map);
                plFloodedContour1 = new List<Polygon>(cont.FloodedContour_1(dtFile.Zones.Top()));
                //SetPolygons(polys);

                //DisableAllSurface();
                
            }
            RefreshPolygons();
            Invalidate();
            floodedContoursMethod1ToolStripMenuItem.Checked = !floodedContoursMethod1ToolStripMenuItem.Checked;
        }
        #endregion

        #region Line Fillers
        private void edgeColoringToolStripMenuItem_Click(object sender, EventArgs e)
		{
            if (edgeColoringToolStripMenuItem.Checked)
                lnEdgeColor = null;
            //LinesVb = null;
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                SimpleColoring clr = new SimpleColoring(map, ChooseVariable(false));
                lnEdgeColor = new List<VisualizationPackage.FileLoader.Line>(clr.EdgeColoring(dtFile.Zones.Top()));
                //SetLines(lines);
                //DisableAllLine();
            }
            RefreshLines();
            Invalidate();
            edgeColoringToolStripMenuItem.Checked = !edgeColoringToolStripMenuItem.Checked;
		}
        private void lineContoursToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lineContoursToolStripMenuItem.Checked)
                lnLineContour = null;
            //LinesVb = null;
            else
            {
                if (!BuildColorMap(ChooseVariable(true)))
                    return;
                Contour cont = new Contour(GlobalVariables.Get(ChooseVariable(false)), map);
                lnLineContour = new List<VisualizationPackage.FileLoader.Line>(cont.LineContour(dtFile.Zones.Top()));
                
                //SetLines(lines);
                //DisableAllLine();
            }
            RefreshLines();
            Invalidate();
            lineContoursToolStripMenuItem.Checked = !lineContoursToolStripMenuItem.Checked;
        }
        private void streamLinesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int[] vector = ChooseVector(true);
            if (vector.Length <= 2)
                return;

            lnStreamLine = new List<VisualizationPackage.FileLoader.Line>();// (slines.Calculate(dtFile.Zones.Top()));
            foreach (StreamLine sLine in StreamLine.StreamLines)
                lnStreamLine.AddRange(sLine.Calculate());

            //// Get Mesh Lines
            //map.Map.Clear();
            //map[0] = Color.LightBlue;
            //SimpleColoring clr = new SimpleColoring(map, Constants.X_Coord);
            //lines.AddRange(clr.EdgeColoring(dtFile.Zones.Top()));
            //// End Get Mesh Lines
            //if (lines.Count > 0)
            //{
            //    SetLines(lines);
            //    DisableAllLine();
            //}

            plStreamRibon = new List<Polygon>();
            foreach (StreamRibon stRibon in StreamRibon.StreamRibons)
                plStreamRibon.AddRange(stRibon.Calculate());
            //if (polygons.Count > 0)
            //    SetPolygons(polygons);
            RefreshLines();
            RefreshPolygons();

            Invalidate();
        }
        private void meshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (meshToolStripMenuItem.Checked)
                lnMesh = null;
            //LinesVb = null;
            else
                DrawMesh();
            RefreshLines();
            meshToolStripMenuItem.Checked = !meshToolStripMenuItem.Checked;
            Invalidate();
        }
        private void streamRibonsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmStreamRibon frmRibons = new frmStreamRibon();
            frmRibons.DataSource = StreamLine.StreamLines;
            DialogResult res = frmRibons.ShowDialog();
            if (res == DialogResult.OK)
            {
                StreamRibon stRibon = new StreamRibon(StreamLine.StreamLines[frmRibons.SelectedStreamLine]);
                stRibon.Calculate();
                plStreamRibon = new List<Polygon>(stRibon.Path);
                RefreshPolygons();
                //SetPolygons(new List<Polygon>(stRibon.Path));
                Invalidate();
            }
        }
        #endregion

        private void invalidateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Invalidate();
        }

        private string ChooseVariable(bool forceShow)
        {
            if (forceShow)
            {
                if (dtFile == null)
                    return "";
                List<string> lst = new List<string>((IEnumerable<string>)GlobalVariables.Data.Values);
                vars.DataSource = new System.Collections.ObjectModel.ReadOnlyCollection<string>(lst);
                DialogResult res = vars.ShowDialog();
                if (res == DialogResult.OK)
                    return vars.SelectedVariable.ToUpper();
                else
                {
                    return "";
                    if (dtFile.VarToIndex.Keys.Count > 0)
                        foreach (string str in dtFile.VarToIndex.Keys)
	                    {
                            return str;
	                    }
                    return "";
                }
            }
            else
                return vars.SelectedVariable.ToUpper();
        }
        private int[] ChooseVector(bool forceShow)
        {
            if (forceShow)
            {
                if (dtFile == null)
                    return new int[] { 0 };
                List<string> lst = new List<string>((IEnumerable<string>)GlobalVariables.Data.Values);
                //if (dtFile.Zones.Top().ElementType == Visualization.ElementType.IJKBrick ||
                //    dtFile.Zones.Top().ElementType == Visualization.ElementType.IJKQuad)
                //{
                //    lst.Add("X");
                //    lst.Add("Y");
                //    lst.Add("Z");
                //}
                varsVector.DataSource = new System.Collections.ObjectModel.ReadOnlyCollection<string>(lst);
                varsVector.Mesh = dtFile;
                DialogResult res = varsVector.ShowDialog();
                if (res == DialogResult.OK)
                    return new int[] { varsVector.UField, varsVector.VField, varsVector.WField };
                else
                    return new int[] { };
            }
            else
                return new int[] { varsVector.UField, varsVector.VField };
        }
        private void visualizationToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void customizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmColorMap colorCustomize = new frmColorMap();
            colorCustomize.ColorsCount = colorsCount;
            DialogResult dlgResult = colorCustomize.ShowDialog();
            if (dlgResult == DialogResult.OK)
            {
                if (colorCustomize.ColorMap != null)
                {
                    mapTemp = colorCustomize.ColorMap;
                    _useExistingColorMap = true;
                }
                else
                {
                    colorsCount = colorCustomize.ColorsCount;
                    _useExistingColorMap = false;
                }
            }
        }
        private void RefreshLines()
        {
            if (LinesVb != null)
                LinesVb = null;

            List<VisualizationPackage.FileLoader.Line> lines = new List<VisualizationPackage.FileLoader.Line>();
            if (lnEdgeColor != null)
                lines.AddRange(lnEdgeColor);
            if (lnLineContour != null)
                lines.AddRange(lnLineContour);
            if (lnMesh != null)
                lines.AddRange(lnMesh);
            if (lnStreamLine != null)
                lines.AddRange(lnStreamLine);

            if (lines.Count > 0)
                SetLines(lines);
        }
        private void RefreshPolygons()
        {
            if (Polygons != null)
                Polygons.Clear();
            
            List<Polygon> polys = new List<Polygon>();
            if (plFloodedContour1 != null)
                polys.AddRange(plFloodedContour1);
            if (plFloodedContour2 != null)
                polys.AddRange(plFloodedContour2);
            if (plIsoSurface != null)
                polys.AddRange(plIsoSurface);
            if (plStreamRibon != null)
                polys.AddRange(plStreamRibon);
            if (plSurfaceColor != null)
                polys.AddRange(plSurfaceColor);
            
            if (polys.Count > 0)
                SetPolygons(polys);
        }

        private void frmMain_Load(object sender, EventArgs e)
        {

        }
    }
}
